﻿using GoPlay.Models;
using GoPlay.Controllers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
//using GoPlay.Tests.Models;

namespace GoPlay.Tests.Controllers
{
    [TestClass]
    public class GamesControllerTests
    {
        //[TestMethod]
        //public void Game_Index_GET_AsksForIndexView()
        //{
        //    // Arrange
        //    var controller = GetGamesController(new InMemoryRepository<Game>());

        //    // Act
        //    ViewResult result = controller.Index() as ViewResult;

        //    // Assert
        //    Assert.AreNotEqual(null, result);
        //}

        //[TestMethod]
        //public void Game_Index_GET_RetrievesAllGamesFromRepositoryForThisUser()
        //{
        //    // Arrange
        //    Game t = new Game { Name = "test", UserId = 1 };
        //    InMemoryRepository<Game> repository = new InMemoryRepository<Game>();
        //    repository.Insert(t);
        //    t = new Game { Name = "test2", UserId = 2 };
        //    repository.Insert(t);
        //    var controller = GetGamesController(repository);

        //    // Act
        //    ViewResult result = controller.Index() as ViewResult;

        //    // Assert
        //    var model = (IEnumerable<Game>)result.Model;
        //    //CollectionAssert.Contains(model.ToList(), t);
        //    Assert.AreEqual(model.Count(), 1);
        //    Assert.AreEqual("test", model.First().Name);
        //}

        [TestMethod]
        public void Game_Create_POST_PutsValidGameIntoRepository()
        {
            // Arrange
            InMemoryRepository<Game> repository = new InMemoryRepository<Game>();
            GamesController controller = GetGamesController(repository);
            Game Game = new Game { UserId = 1, TeamId = 1, Date=DateTime.Now.ToString("MM/dd/yyyy"), Time="1:15pm", Decision="W", GA="2", GF="3", Id=1 };

            // Act
            controller.Create(Game);

            // Assert
            IEnumerable<Game> Games = repository.GetAllByUserId(1);
            Assert.IsTrue(Games.Contains(Game));
        }

        [TestMethod]
        public void Game_Create_POST_ReturnsRedirectOnSuccess()
        {
            // Arrange
            GamesController controller = GetGamesController(new InMemoryRepository<Game>());
            Game Game = new Game { UserId = 1, TeamId = 1, Date = DateTime.Now.ToString("MM/dd/yyyy"), Time = "1:15pm", Decision = "W", GA = "2", GF = "3", Id = 1 };

            // Act
            var result = (RedirectToRouteResult)controller.Create(Game);

            // Assert
            Assert.AreEqual("Details", result.RouteValues["action"]);
        }

        [TestMethod]
        public void Game_Create_POST_ReturnsViewIfModelStateIsNotValid()
        {
            // Arrange
            GamesController controller = GetGamesController(new InMemoryRepository<Game>());
            // Simply executing a method during a unit test does just that - executes a method, and no more. 
            // The MVC pipeline doesn't run, so binding and validation don't run.
            controller.ModelState.AddModelError("", "mock error message");
            Game Game = new Game { UserId = 1, TeamId = 1, Date = DateTime.Now.ToString("MM/dd/yyyy"), Time = "1:15pm", Decision = "W", GA = "2", GF = "3", Id = 1 };

            // Act
            var result = (ViewResult)controller.Create(Game);

            // Assert
            Assert.AreEqual("GoPlay.Models.Game", result.ViewData.Model.ToString());
        }

        [TestMethod]
        public void Game_Create_POST_ReturnsViewIfRepositoryThrowsException()
        {
            // Arrange
            InMemoryRepository<Game> repository = new InMemoryRepository<Game>();
            Exception exception = new Exception();
            repository.ExceptionToThrow = exception;
            GamesController controller = GetGamesController(repository);
            Game Game = new Game { UserId = 1, TeamId = 1, Date = DateTime.Now.ToString("MM/dd/yyyy"), Time = "1:15pm", Decision = "W", GA = "2", GF = "3", Id = 1 };

            // Act
            var result = controller.Create(Game) as ViewResult;

            // Assert
            ModelState modelState = result.ViewData.ModelState[""];
            Assert.IsNotNull(modelState);
            Assert.IsTrue(modelState.Errors.Any());
            Assert.AreEqual(exception, modelState.Errors[0].Exception);
        }

        [TestMethod]
        public void Game_Edit_POST_UpdatesGameInRepository()
        {
            //// Arrange
            //InMemoryRepository<Game> repository = new InMemoryRepository<Game>();
            //GamesController controller = GetGamesController(repository);
            //Game Game = new Game { Name = "test", UserId = 1 };

            //// Act
            //controller.Create(Game);

            //// Assert
            //IEnumerable<Game> Games = repository.GetAllGamesForUser(1);
            //Assert.IsTrue(Games.Contains(Game));
            Assert.Inconclusive();
        }

        [TestMethod]
        public void Game_Edit_POST_ReturnsRedirectOnSuccess()
        {
            //// Arrange
            //GamesController controller = GetGamesController(new InMemoryRepository<Game>());
            //Game Game = new Game { Name = "test", UserId = 1 };

            //// Act
            //var result = (RedirectToRouteResult)controller.Create(Game);

            //// Assert
            //Assert.AreEqual("Index", result.RouteValues["action"]);
            Assert.Inconclusive();
        }

        [TestMethod]
        public void Game_Edit_POST_ReturnsViewIfModelStateIsNotValid()
        {
            //// Arrange
            //GamesController controller = GetGamesController(new InMemoryRepository<Game>());
            //// Simply executing a method during a unit test does just that - executes a method, and no more. 
            //// The MVC pipeline doesn't run, so binding and validation don't run.
            //controller.ModelState.AddModelError("", "mock error message");
            //Game Game = new Game { Name = "test", UserId = 1 };

            //// Act
            //var result = (ViewResult)controller.Create(Game);

            //// Assert
            //Assert.AreEqual("GoPlay.Models.Game", result.ViewData.Model.ToString());
            Assert.Inconclusive();
        }

        [TestMethod]
        public void Game_Edit_POST_ReturnsViewIfRepositoryThrowsException()
        {
            //// Arrange
            //InMemoryRepository<Game> repository = new InMemoryRepository<Game>();
            //Exception exception = new Exception();
            //repository.ExceptionToThrow = exception;
            //GamesController controller = GetGamesController(repository);
            //Game Game = new Game { Name = "test", UserId = 1 };

            //// Act
            //var result = (ViewResult)controller.Create(Game);

            //// Assert
            //ModelState modelState = result.ViewData.ModelState[""];
            //Assert.IsNotNull(modelState);
            //Assert.IsTrue(modelState.Errors.Any());
            //Assert.AreEqual(exception, modelState.Errors[0].Exception);
            Assert.Inconclusive();
        }



        private static GamesController GetGamesController(IRepository<Game> repository)
        {
            GamesController controller = new GamesController(repository);

            var sessionItems = new SessionStateItemCollection();
            sessionItems["UserId"] = "1";
            sessionItems["UserName"] = "chipirek";
            controller.ControllerContext = new MvcFakes.FakeControllerContext(controller, sessionItems);
            return controller;
        }

    }
}
